﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

#Область СлужебныеПроцедурыИФункции

// Формирует табличный документ отчет.
//
// Параметры:
//  ТаблицаОтчета - ТабличныйДокумент - документ, в который выводятся данные.
//  Опрос  - ДокументСсылка.НазначениеОпросов - опрос, по которому формируется отчет.
//  ВидОтчета - Строка - может принимать значения АнализОтветов и АнализОтветивших.
//
Процедура СформироватьОтчет(ТаблицаОтчета,Опрос,ВидОтчета) Экспорт
	
	ТаблицаОтчета.Очистить();
	
	Если ВидОтчета ="АнализОтветов" Тогда
		
		СформироватьОтчетАнализОтветов(ТаблицаОтчета,Опрос);
		
	ИначеЕсли ВидОтчета = "АнализОтветивших" Тогда
		
		СформироватьОтчетАнализОтветивших(ТаблицаОтчета,Опрос);
		
	Иначе
		
		Возврат;
		
	КонецЕсли;
	
КонецПроцедуры

#Область АнализОтветов

// Параметры:
//  ТаблицаОтчета - ТабличныйДокумент
//  Опрос - ДокументСсылка.НазначениеОпросов
//
Процедура СформироватьОтчетАнализОтветов(ТаблицаОтчета, Опрос)
	
	РеквизитыОпроса = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Опрос, "ШаблонАнкеты,ДатаНачала,ДатаОкончания,Представление");
	ШаблонАнкеты = РеквизитыОпроса.ШаблонАнкеты;
	ПредставленияВопросов = Анкетирование.ПредставленияЭлементарныхВопросовТабличногоВопроса(ШаблонАнкеты);
	
	РезультатЗапроса = ВыполнитьЗапросПоВопросамШаблонаАнкеты(Опрос,ШаблонАнкеты);
	Если РезультатЗапроса.Пустой() Тогда
		Возврат;	
	КонецЕсли;
	
	Макет = ПолучитьМакет("МакетОтветы");
	
	Область = Макет.ПолучитьОбласть("Заголовок"); // ТабличныйДокумент
	Область.Параметры.Заголовок = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ШаблонАнкеты, "Заголовок");
	Область.Параметры.Опрос     = ПредставлениеОпросаДляЗаголовка(РеквизитыОпроса);
	ТаблицаОтчета.Вывести(Область, 1);
	
	Область = Макет.ПолучитьОбласть("ПустаяСтрока");
	ТаблицаОтчета.Вывести(Область, 1);
	ТаблицаОтчета.НачатьГруппуСтрок("Аннотация");
	
	Область = Макет.ПолучитьОбласть("Аннотация");
	ТаблицаОтчета.Вывести(Область, 2);
	ТаблицаОтчета.ЗакончитьГруппуСтрок();
	
	Область = Макет.ПолучитьОбласть("ПустаяСтрока");
	ТаблицаОтчета.Вывести(Область, 1);
	
	ДеревоАнкеты = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
	Если ДеревоАнкеты.Строки.Количество() > 0 Тогда
		ВывестиВТабличныйДокумент(ДеревоАнкеты.Строки,ТаблицаОтчета,Макет,1,Новый Массив, ПредставленияВопросов);
	КонецЕсли;
	
КонецПроцедуры 

// Вызывается рекурсивно, формирует полный код, и вызывает процедуры вывода вопросов и разделов .
//
// Параметры:
//  СтрокиДерева    - КоллекцияСтрокДереваЗначений - строки дерева, для которых выполняется действие.
//  ТаблицаОтчета   - ТабличныйДокумент -  в него осуществляется вывод данных.
//  Макет           - ТабличныйДокумент - макет, используемый для вывода данных.
//  УровеньРекурсии - Число             - текущий уровень рекурсии.
//  МассивПолныйКод - Массив            - используется для формирования полного когда обрабатываемой строки.
// 
Процедура ВывестиВТабличныйДокумент(СтрокиДерева,ТаблицаОтчета,Макет,УровеньРекурсии,МассивПолныйКод, ПредставленияВопросов)
	
	Если МассивПолныйКод.Количество() < УровеньРекурсии Тогда
		МассивПолныйКод.Добавить(0);
	КонецЕсли;
	
	Для каждого СтрокаДерева Из СтрокиДерева Цикл
		
		МассивПолныйКод[УровеньРекурсии-1] = МассивПолныйКод[УровеньРекурсии-1] + 1;
		Для инд = УровеньРекурсии По МассивПолныйКод.Количество()-1 Цикл
			МассивПолныйКод[инд] = 0;
		КонецЦикла;
		
		ПолныйКод = СтрСоединить(МассивПолныйКод,".");
		ПолныйКод = АнкетированиеКлиентСервер.УдалитьПоследниеСимволыИзСтроки(ПолныйКод,"0.",".");
		
		Если СтрокаДерева.ЭтоРаздел Тогда
			ВывестиРаздел(ТаблицаОтчета,СтрокаДерева,Макет,ПолныйКод);
			Если СтрокаДерева.Строки.Количество() > 0 Тогда
				ВывестиВТабличныйДокумент(СтрокаДерева.Строки,ТаблицаОтчета,Макет,УровеньРекурсии + 1,МассивПолныйКод,ПредставленияВопросов);
			КонецЕсли
		Иначе
			ВывестиВопрос(ТаблицаОтчета,СтрокаДерева,Макет,ПолныйКод, ПредставленияВопросов);
		КонецЕсли;
		ТаблицаОтчета.ЗакончитьГруппуСтрок();
		
	КонецЦикла;
	
КонецПроцедуры

// Параметры:
//  ТаблицаОтчета - ТабличныйДокумент - в него осуществляется вывод информации.
//  СтрокаДерева  - СтрокаДереваЗначений - текущая строка с данными:
//   * Наименование - Строка
//  Макет         - ТабличныйДокумент - макет, используемый для вывода информации.
//  ПолныйКод     - Строка - полный код строки, выводимой в отчет.
// 
Процедура ВывестиРаздел(ТаблицаОтчета,СтрокаДерева,Макет,ПолныйКод)
	
	Область = Макет.ПолучитьОбласть("Раздел");
	Область.Параметры.ИмяРаздела = ПолныйКод + " " + СтрокаДерева.Наименование;
	ТаблицаОтчета.Вывести(Область);
	ТаблицаОтчета.НачатьГруппуСтрок("ПолныйКод_" + СтрокаДерева.Наименование);
	
КонецПроцедуры

// Параметры:
//  ТаблицаОтчета - ТабличныйДокумент - в него осуществляется вывод информации.
//  СтрокаДерева  - СтрокаДереваЗначений - текущая строка с данными:
//   * Наименование - Строка
//  Макет         - ТабличныйДокумент - макет, используемый для вывода информации.
//  Полный код    - Строка - полный код строки, выводимой в отчет.
//
Процедура ВывестиВопрос(ТаблицаОтчета,СтрокаДерева,Макет,ПолныйКод, ПредставленияВопросов)
	
	Область = Макет.ПолучитьОбласть("Вопрос");
	Область.Параметры.ФормулировкаВопроса = ПолныйКод + " " + СтрокаДерева.Наименование;
	ТаблицаОтчета.Вывести(Область);
	ТаблицаОтчета.НачатьГруппуСтрок("ПолныйКод_" + СтрокаДерева.Наименование);
	
	Если СтрокаДерева.Строки.Количество() > 0 Тогда		
		
		Если СтрокаДерева.ТипВопроса = Перечисления.ТипыВопросовШаблонаАнкеты.Табличный Тогда
			
			ВывестиОтветТабличныйВопрос(ТаблицаОтчета,СтрокаДерева,Макет,ПолныйКод,ПредставленияВопросов);
			
		Иначе	
			
			ВывестиОтветПростойВопрос(ТаблицаОтчета,СтрокаДерева,Макет,ПолныйКод);
			
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

// Параметры:
//  ТаблицаОтчета         - ТабличныйДокумент - в него осуществляется вывод информации.
//  СтрокаДерева          - СтрокаДереваЗначений - текущая строка с данными.
//  Макет                 - ТабличныйДокумент - макет, используемый для вывода информации.
//  ПолныйКод             - Строка - полный код строки, выводимой в отчет.
//  ПредставленияВопросов - Соответствие - содержит информацию о формулировке и признаке "Агрегировать в отчетах". 
// 
Процедура ВывестиОтветТабличныйВопрос(ТаблицаОтчета, СтрокаДерева, Макет, ПолныйКод, ПредставленияВопросов)
	
	Если СтрокаДерева.ТипТабличногоВопроса = Перечисления.ТипыТабличныхВопросов.Составной Тогда
		
		ВывестиОтветСоставнойТабличныйВопрос(ТаблицаОтчета,СтрокаДерева.Строки[0],Макет,ПолныйКод, ПредставленияВопросов);
		
	ИначеЕсли СтрокаДерева.ТипТабличногоВопроса = Перечисления.ТипыТабличныхВопросов.ПредопределенныеОтветыВКолонках Тогда
		
		ВывестиОтветПредопределенныеОтветыВКолонкахТабличныйВопрос(ТаблицаОтчета,СтрокаДерева,Макет,ПолныйКод,ПредставленияВопросов);
		
	ИначеЕсли СтрокаДерева.ТипТабличногоВопроса = Перечисления.ТипыТабличныхВопросов.ПредопределенныеОтветыВСтроках Тогда
		
		ВывестиОтветПредопределенныеОтветыВСтрокахТабличныйВопрос(ТаблицаОтчета,СтрокаДерева,Макет,ПолныйКод,ПредставленияВопросов);
		
	ИначеЕсли СтрокаДерева.ТипТабличногоВопроса = Перечисления.ТипыТабличныхВопросов.ПредопределенныеОтветыВСтрокахИКолонках Тогда
		
		ВывестиОтветПредопределенныеОтветыВСтрокахИКолонкахТабличныйВопрос(ТаблицаОтчета,СтрокаДерева,Макет,ПолныйКод, ПредставленияВопросов);
		
	КонецЕсли;
	
КонецПроцедуры

// Выводит в таблицу отчета ответы табличного вопроса с предопределенными ответами в колонках.
//
// Параметры:
//  ТаблицаОтчета         - ТабличныйДокумент - в него осуществляется вывод информации.
//  СтрокаДерева          - СтрокаДереваЗначений - текущая строка с данными.
//  Макет                 - ТабличныйДокумент - макет, используемый для вывода информации.
//  ПолныйКод             - Строка - полный код строки, выводимой в отчет.
//  ПредставленияВопросов - Соответствие - содержит информацию о формулировке и признаке "Агрегировать в отчетах". 
//
Процедура ВывестиОтветПредопределенныеОтветыВКолонкахТабличныйВопрос(ТаблицаОтчета, СтрокаДерева, Макет, ПолныйКод, ПредставленияВопросов)
	
	СтрокаДереваДетали = СтрокаДерева.Строки[0];
	
	Область = Макет.ПолучитьОбласть("Отступ");
	ТаблицаОтчета.Вывести(Область);
	
	Область = Макет.ПолучитьОбласть("ЭлементШапкиТабличногоВопроса");
	ТаблицаОтчета.Присоединить(Область);
	
	СтрокаДереваДетали.ПредопределенныеОтветы.Сортировать("НомерСтроки Возр");
	СтрокаДереваДетали.СоставТабличногоВопроса.Сортировать("НомерСтроки Возр");
	Для Каждого Ответ Из СтрокаДереваДетали.ПредопределенныеОтветы Цикл
		
		Область = Макет.ПолучитьОбласть("ЭлементШапкиТабличногоВопроса");
		Область.Параметры.Значение = Ответ.Ответ;
		ТаблицаОтчета.Присоединить(Область);
		
	КонецЦикла;
	
	Для ИндексСтрок = 2 По СтрокаДереваДетали.СоставТабличногоВопроса.Количество() Цикл
		
		Область = Макет.ПолучитьОбласть("Отступ");
		ТаблицаОтчета.Вывести(Область);
		
		Область = Макет.ПолучитьОбласть("ЭлементШапкиТабличногоВопроса");
		Область.Параметры.Значение = ПредставленияВопросов.Получить(СтрокаДереваДетали.СоставТабличногоВопроса[ИндексСтрок - 1].ЭлементарныйВопрос).Формулировка;
		ТаблицаОтчета.Присоединить(Область);
		
		Для ИндексКолонок = 1 По СтрокаДереваДетали.ПредопределенныеОтветы.Количество() Цикл
			
			СтруктураОтбора = Новый Структура;
			СтруктураОтбора.Вставить("ЭлементарныйВопросРегистр",СтрокаДереваДетали.СоставТабличногоВопроса[ИндексСтрок-1].ЭлементарныйВопрос);
			СтруктураОтбора.Вставить("НомерЯчейки",ИндексКолонок);
			НайденныеСтроки = СтрокаДерева.Строки.НайтиСтроки(СтруктураОтбора);
			
			Область = Макет.ПолучитьОбласть("ЯчейкаТабличногоВопроса");
			Если НайденныеСтроки.Количество() > 0 Тогда
				Если ТипЗнч(НайденныеСтроки[0].ВариантОтвета) <> Тип("Булево") Тогда
					Область.Параметры.Значение = АгрегатныеЗначенияВСтроку(НайденныеСтроки[0],ПредставленияВопросов.Получить(СтрокаДереваДетали.СоставТабличногоВопроса[ИндексСтрок-1].ЭлементарныйВопрос).АгрегироватьСуммуВОтчетах);
					Область.Параметры.Расшифровка = Новый Структура("ВопросШаблона,ТипВопроса,ПолныйКод",СтрокаДерева.ВопросШаблона,СтрокаДерева.ТипВопроса,ПолныйКод);
				Иначе
					Для каждого НайденнаяСтрока Из НайденныеСтроки Цикл
						Если НайденнаяСтрока.ВариантОтвета = Истина Тогда
							Область.Параметры.Значение = НайденнаяСтрока.Количество;
							Область.Параметры.Расшифровка = Новый Структура("ВопросШаблона,ТипВопроса,ПолныйКод",СтрокаДерева.ВопросШаблона,СтрокаДерева.ТипВопроса,ПолныйКод);
						КонецЕсли;
					КонецЦикла;
				КонецЕсли;
			КонецЕсли;
			ТаблицаОтчета.Присоединить(Область);
			
		КонецЦикла;
		
	КонецЦикла;
		
КонецПроцедуры

// Параметры:
//  ТаблицаОтчета         - ТабличныйДокумент - в него осуществляется вывод информации.
//  СтрокаДерева          - СтрокаДереваЗначений - текущая строка с данными.
//  Макет                 - ТабличныйДокумент - макет, используемый для вывода информации.
//  ПолныйКод             - Строка - полный код строки, выводимой в отчет.
//  ПредставленияВопросов - Соответствие - содержит информацию о формулировке и признаке "Агрегировать в отчетах". 
//
Процедура ВывестиОтветПредопределенныеОтветыВСтрокахТабличныйВопрос(ТаблицаОтчета, СтрокаДерева, Макет, ПолныйКод, ПредставленияВопросов)
	
	ПерваяКолонка = Истина;
	СтрокаДереваДетали = СтрокаДерева.Строки[0];
	СтрокаДереваДетали.ПредопределенныеОтветы.Сортировать("НомерСтроки Возр");
	СтрокаДереваДетали.СоставТабличногоВопроса.Сортировать("НомерСтроки Возр");
	
	Для каждого Вопрос Из СтрокаДереваДетали.СоставТабличногоВопроса Цикл
		
		Если ПерваяКолонка Тогда
			Область = Макет.ПолучитьОбласть("Отступ");
			ТаблицаОтчета.Вывести(Область);
			ПерваяКолонка = Ложь;
		КонецЕсли;
		
		Область = Макет.ПолучитьОбласть("ЭлементШапкиТабличногоВопроса");
		Область.Параметры.Значение = ПредставленияВопросов.Получить(Вопрос.ЭлементарныйВопрос).Формулировка;
		ТаблицаОтчета.Присоединить(Область); 
		
	КонецЦикла;
	
	Для ИндексСтрок = 1 По СтрокаДереваДетали.ПредопределенныеОтветы.Количество() Цикл
		
		ПерваяКолонка = Истина;
		
		Для ИндексКолонок = 1 По СтрокаДереваДетали.СоставТабличногоВопроса.Количество() Цикл
			
			Если ПерваяКолонка Тогда
				
				Область = Макет.ПолучитьОбласть("Отступ");
				ТаблицаОтчета.Вывести(Область);
				ПерваяКолонка = Ложь;
				
				Область = Макет.ПолучитьОбласть("ЭлементЯчейкиТабличногоВопросаПредопределенныйОтвет");
				Область.Параметры.Значение = СтрокаДереваДетали.ПредопределенныеОтветы[ИндексСтрок -1].Ответ;
				ТаблицаОтчета.Присоединить(Область);
				
			Иначе
				
				СтруктураОтбора = Новый Структура;
				СтруктураОтбора.Вставить("ЭлементарныйВопросРегистр",СтрокаДереваДетали.СоставТабличногоВопроса[ИндексКолонок-1].ЭлементарныйВопрос);
				СтруктураОтбора.Вставить("НомерЯчейки",ИндексСтрок);
				НайденныеСтроки = СтрокаДерева.Строки.НайтиСтроки(СтруктураОтбора);
				
				Область = Макет.ПолучитьОбласть("ЯчейкаТабличногоВопроса");
				Если НайденныеСтроки.Количество() > 0 Тогда
					Если ТипЗнч(НайденныеСтроки[0].ВариантОтвета) <> Тип("Булево") Тогда
						Область.Параметры.Значение = АгрегатныеЗначенияВСтроку(НайденныеСтроки[0],ПредставленияВопросов.Получить(СтрокаДереваДетали.СоставТабличногоВопроса[ИндексКолонок-1].ЭлементарныйВопрос).АгрегироватьСуммуВОтчетах);
						Область.Параметры.Расшифровка = Новый Структура("ВопросШаблона,ТипВопроса,ПолныйКод",СтрокаДереваДетали.ВопросШаблона,СтрокаДереваДетали.ТипВопроса,ПолныйКод);
					Иначе
						Для каждого НайденнаяСтрока Из НайденныеСтроки Цикл
							Если НайденнаяСтрока.ВариантОтвета = Истина Тогда
								Область.Параметры.Значение = НайденнаяСтрока.Количество;
								Область.Параметры.Расшифровка = Новый Структура("ВопросШаблона,ТипВопроса,ПолныйКод",СтрокаДереваДетали.ВопросШаблона,СтрокаДереваДетали.ТипВопроса,ПолныйКод);
							КонецЕсли;
						КонецЦикла;
					КонецЕсли;
				КонецЕсли;
				ТаблицаОтчета.Присоединить(Область);
				
			КонецЕсли;
			
		КонецЦикла;
	КонецЦикла;
	
КонецПроцедуры

// Выводит в таблицу отчета ответы табличного вопроса с предопределенными ответами в строках и колонках.
//
// Параметры:
//  ТаблицаОтчета         - ТабличныйДокумент - в него осуществляется вывод информации.
//  СтрокаДерева          - СтрокаДереваЗначений - текущая строка с данными.
//  Макет                 - ТабличныйДокумент - макет, используемый для вывода информации.
//  ПолныйКод             - Строка - полный код строки, выводимой в отчет.
//  ПредставленияВопросов - Соответствие - содержит информацию о формулировке и признаке "Агрегировать в отчетах". 
//
Процедура ВывестиОтветПредопределенныеОтветыВСтрокахИКолонкахТабличныйВопрос(ТаблицаОтчета, СтрокаДерева, Макет, ПолныйКод, ПредставленияВопросов)
	
	СтрокаДереваДетали = СтрокаДерева.Строки[0];
	
	СтрокаДереваДетали.ПредопределенныеОтветы.Сортировать("НомерСтроки Возр");
	СтрокаДереваДетали.СоставТабличногоВопроса.Сортировать("НомерСтроки Возр");

	Если СтрокаДереваДетали.СоставТабличногоВопроса.Количество() <> 3 Тогда
		Возврат;
	КонецЕсли;
	
	АгрегироватьСуммуВОтчетах = ПредставленияВопросов.Получить(СтрокаДереваДетали.СоставТабличногоВопроса[2].ЭлементарныйВопрос).АгрегироватьСуммуВОтчетах;
	
	ОтветыКолонки = СтрокаДереваДетали.ПредопределенныеОтветы.НайтиСтроки(Новый Структура("ЭлементарныйВопросОтвет",СтрокаДереваДетали.СоставТабличногоВопроса[1].ЭлементарныйВопрос));
	ОтветыСтроки = СтрокаДереваДетали.ПредопределенныеОтветы.НайтиСтроки(Новый Структура("ЭлементарныйВопросОтвет",СтрокаДереваДетали.СоставТабличногоВопроса[0].ЭлементарныйВопрос));
	
	Если ОтветыКолонки.Количество() = 0 И ОтветыСтроки.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	Область = Макет.ПолучитьОбласть("Отступ");
	ТаблицаОтчета.Вывести(Область);
	
	Область = Макет.ПолучитьОбласть("ЭлементШапкиТабличногоВопроса");
	ТаблицаОтчета.Присоединить(Область);
	
	Для Каждого Ответ Из ОтветыКолонки Цикл
		
		Область = Макет.ПолучитьОбласть("ЭлементШапкиТабличногоВопроса");
		Область.Параметры.Значение = Ответ.Ответ;
		ТаблицаОтчета.Присоединить(Область);
		
	КонецЦикла;
	
	Для ИндексСтроки = 1 По ОтветыСтроки.Количество()  Цикл
		
		Область = Макет.ПолучитьОбласть("Отступ");
		ТаблицаОтчета.Вывести(Область);
		
		Область = Макет.ПолучитьОбласть("ЭлементШапкиТабличногоВопроса");
		Область.Параметры.Значение = ОтветыСтроки[ИндексСтроки - 1].Ответ;
		ТаблицаОтчета.Присоединить(Область);
		
		Для ИндексКолонки = 1 По ОтветыКолонки.Количество() Цикл
			
			СтруктураОтбора = Новый Структура;
			СтруктураОтбора.Вставить("НомерЯчейки", ИндексКолонки + (ИндексСтроки-1) * ОтветыКолонки.Количество());
			СтруктураОтбора.Вставить("ЭлементарныйВопросРегистр",СтрокаДереваДетали.СоставТабличногоВопроса[2].ЭлементарныйВопрос);
			НайденныеСтроки = СтрокаДерева.Строки.НайтиСтроки(СтруктураОтбора);
			
			Область = Макет.ПолучитьОбласть("ЯчейкаТабличногоВопроса");
			Если НайденныеСтроки.Количество() > 0 Тогда
				Если ТипЗнч(НайденныеСтроки[0].ВариантОтвета) <> Тип("Булево") Тогда
					Область.Параметры.Значение = АгрегатныеЗначенияВСтроку(НайденныеСтроки[0],АгрегироватьСуммуВОтчетах);
					Область.Параметры.Расшифровка = Новый Структура("ВопросШаблона,ТипВопроса,ПолныйКод",СтрокаДерева.ВопросШаблона,СтрокаДерева.ТипВопроса,ПолныйКод);
				Иначе
					Для каждого НайденнаяСтрока Из НайденныеСтроки Цикл
						Если НайденнаяСтрока.ВариантОтвета = Истина Тогда
							Область.Параметры.Значение = НайденнаяСтрока.Количество;
							Область.Параметры.Расшифровка = Новый Структура("ВопросШаблона,ТипВопроса",СтрокаДерева.ВопросШаблона,СтрокаДерева.ТипВопроса,ПолныйКод);
						КонецЕсли;
					КонецЦикла;
				КонецЕсли;
			КонецЕсли;
			ТаблицаОтчета.Присоединить(Область);
		КонецЦикла;
		
	КонецЦикла;
	
КонецПроцедуры

// Параметры:
//  ТаблицаОтчета         - ТабличныйДокумент - в него осуществляется вывод информации.
//  СтрокаДерева          - СтрокаДереваЗначений - текущая строка с данными.
//  Макет                 - ТабличныйДокумент - макет, используемый для вывода информации.
//  ПолныйКод             - Строка - полный код строки, выводимой в отчет.
//  ПредставленияВопросов - Соответствие - содержит информацию о формулировке и признаке "Агрегировать в отчетах".
//
Процедура ВывестиОтветСоставнойТабличныйВопрос(ТаблицаОтчета, СтрокаДерева, Макет, ПолныйКод, ПредставленияВопросов)
	
	ПерваяКолонка = Истина;
	
	СтрокаДерева.СоставТабличногоВопроса.Сортировать("НомерСтроки Возр");
	Для каждого Вопрос Из СтрокаДерева.СоставТабличногоВопроса Цикл
		
		Если ПерваяКолонка Тогда
			Область = Макет.ПолучитьОбласть("Отступ");
			ТаблицаОтчета.Вывести(Область);
			ПерваяКолонка = Ложь;
		КонецЕсли;
		
		Область = Макет.ПолучитьОбласть("ЭлементШапкиТабличногоВопроса");
		Область.Параметры.Значение = ПредставленияВопросов.Получить(Вопрос.ЭлементарныйВопрос).Формулировка;
		ТаблицаОтчета.Присоединить(Область); 
		
	КонецЦикла;
	
	Для ИндексСтрок = 1 По 3 Цикл
		
		ПерваяКолонка = Истина;
		
		Для ИндексКолонок = 1 По СтрокаДерева.СоставТабличногоВопроса.Количество() Цикл
			
			Если ПерваяКолонка Тогда
				Область = Макет.ПолучитьОбласть("Отступ");
				ТаблицаОтчета.Вывести(Область);
				ПерваяКолонка = Ложь;
			КонецЕсли;
			
			Область = Макет.ПолучитьОбласть("ЯчейкаТабличногоВопроса");
			Область.Параметры.Расшифровка = Новый Структура("ВопросШаблона,ТипВопроса,ПолныйКод",СтрокаДерева.ВопросШаблона,СтрокаДерева.ТипВопроса,ПолныйКод);
			ТаблицаОтчета.Присоединить(Область);
			
		КонецЦикла;
	КонецЦикла;
	
КонецПроцедуры

// Параметры:
//  ТаблицаОтчета         - ТабличныйДокумент - в него осуществляется вывод информации.
//  СтрокаДерева          - СтрокаДереваЗначений - текущая строка с данными.
//  Макет                 - ТабличныйДокумент - макет, используемый для вывода информации.
//  ПолныйКод             - Строка - полный код строки, выводимой в отчет.
//
Процедура ВывестиОтветПростойВопрос(ТаблицаОтчета, СтрокаДерева, Макет, ПолныйКод)
	
	СтрокаДереваДетали = СтрокаДерева.Строки[0];
	
	Если СтрокаДереваДетали.ТипОтвета = Перечисления.ТипыОтветовНаВопрос.Булево
		ИЛИ СтрокаДереваДетали.ТипОтвета = Перечисления.ТипыОтветовНаВопрос.ОдинВариантИз
		ИЛИ СтрокаДереваДетали.ТипОтвета = Перечисления.ТипыОтветовНаВопрос.НесколькоВариантовИз Тогда
		
		ВывестиОтветВариантыОтвета(ТаблицаОтчета,СтрокаДерева,Макет,ПолныйКод);
		
	Иначе
		
		Область = Макет.ПолучитьОбласть("ОтветПростогоВопроса");
		Область.Параметры.Значение = АгрегатныеЗначенияВСтроку(СтрокаДереваДетали);
		Область.Параметры.Расшифровка = Новый Структура("ВопросШаблона,ТипВопроса,ПолныйКод",СтрокаДерева.ВопросШаблона,СтрокаДерева.ТипВопроса,ПолныйКод);
		ТаблицаОтчета.Вывести(Область);
		
	КонецЕсли;
	
КонецПроцедуры

// Параметры:
// Параметры:
//  ТаблицаОтчета         - ТабличныйДокумент - в него осуществляется вывод информации.
//  СтрокаДерева          - СтрокаДереваЗначений - текущая строка с данными.
//  Макет                 - ТабличныйДокумент - макет, используемый для вывода информации.
//  ПолныйКод             - Строка - полный код строки, выводимой в отчет.
//
Процедура ВывестиОтветВариантыОтвета(ТаблицаОтчета,СтрокаДерева,Макет,ПолныйКод)
	
	Если СтрокаДерева.Строки[0].ТипОтвета = Перечисления.ТипыОтветовНаВопрос.Булево Тогда
		
		Область = Макет.ПолучитьОбласть("ВариантыОтветов");
		Область.Параметры.ВариантОтвета = НСтр("ru = 'Да'");
		НайденнаяСтрока = СтрокаДерева.Строки.Найти(Истина,"ВариантОтвета");
		Если НайденнаяСтрока <> Неопределено Тогда
			Область.Параметры.Значение = НайденнаяСтрока.Количество;
			Область.Параметры.Расшифровка =Новый Структура("ВопросШаблона,ТипВопроса,ПолныйКод",СтрокаДерева.ВопросШаблона,СтрокаДерева.ТипВопроса,ПолныйКод);
		КонецЕсли;
		ТаблицаОтчета.Вывести(Область);
		
		Область = Макет.ПолучитьОбласть("ВариантыОтветов");
		Область.Параметры.ВариантОтвета = НСтр("ru = 'Нет'");
		НайденнаяСтрока = СтрокаДерева.Строки.Найти(ЛОЖЬ,"ВариантОтвета");
		Если НайденнаяСтрока <> Неопределено Тогда
			Область.Параметры.Значение = НайденнаяСтрока.Количество;
			Область.Параметры.Расшифровка = Новый Структура("ВопросШаблона,ТипВопроса,ПолныйКод",СтрокаДерева.ВопросШаблона,СтрокаДерева.ТипВопроса,ПолныйКод);
		КонецЕсли;
		ТаблицаОтчета.Вывести(Область);
		
	Иначе	
		
		Для каждого СтрокаДетали Из СтрокаДерева.Строки Цикл
			
			Область = Макет.ПолучитьОбласть("ВариантыОтветов");
			Область.Параметры.ВариантОтвета = СтрокаДетали.ВариантОтвета;
			Область.Параметры.Значение = СтрокаДетали.Количество;
			Область.Параметры.Расшифровка = Новый Структура("ВопросШаблона,ТипВопроса,ПолныйКод",СтрокаДерева.ВопросШаблона,СтрокаДерева.ТипВопроса,ПолныйКод);
			ТаблицаОтчета.Вывести(Область);
			
		КонецЦикла;
	КонецЕсли;
	
КонецПроцедуры

// Параметры:
//  Опрос  - ДокументСсылка.НазначениеОпросов - опрос, по которому строится запрос.
//  ШаблонАнкеты - СправочникСсылка.ШаблоныАнкет - по которому проводился опрос.
//
// Возвращаемое значение:
//   РезультатЗапроса   - результат выполненного запроса.
//
Функция ВыполнитьЗапросПоВопросамШаблонаАнкеты(Опрос,ШаблонАнкеты)
	
	Запрос = Новый Запрос;
	Запрос.Текст = " 
	|ВЫБРАТЬ
	|	ОтветыНаВопросыАнкет.Вопрос КАК Вопрос,
	|	ОтветыНаВопросыАнкет.ЭлементарныйВопрос КАК ЭлементарныйВопрос,
	|	ОтветыНаВопросыАнкет.НомерЯчейки КАК НомерЯчейки,
	|	ОтветыНаВопросыАнкет.Ответ КАК ВариантОтвета,
	|	КОЛИЧЕСТВО(ОтветыНаВопросыАнкет.Ответ) КАК КоличествоРазличных
	|ПОМЕСТИТЬ ДанныеРегистраБулевоВариантыОтветов
	|ИЗ
	|	РегистрСведений.ОтветыНаВопросыАнкет КАК ОтветыНаВопросыАнкет
	|ГДЕ
	|	ОтветыНаВопросыАнкет.Анкета.Опрос = &Опрос
	|	И ТИПЗНАЧЕНИЯ(ОтветыНаВопросыАнкет.Ответ) В (ТИП(БУЛЕВО), ТИП(Справочник.ВариантыОтветовАнкет))
	|			
	|СГРУППИРОВАТЬ ПО
	|	ОтветыНаВопросыАнкет.Вопрос,
	|	ОтветыНаВопросыАнкет.ЭлементарныйВопрос,
	|	ОтветыНаВопросыАнкет.НомерЯчейки,
	|	ОтветыНаВопросыАнкет.Ответ
	|;
	|////////////////////////////////////////////////////////////////////
	|
	|ВЫБРАТЬ
	|	ОтветыНаВопросыАнкет.Вопрос КАК Вопрос,
	|	ОтветыНаВопросыАнкет.ЭлементарныйВопрос КАК ЭлементарныйВопрос,
	|	ОтветыНаВопросыАнкет.НомерЯчейки КАК НомерЯчейки,
	|	NULL КАК ВариантОтвета,
	|	МИНИМУМ(ОтветыНаВопросыАнкет.Ответ) КАК МИНИМУМ,
	|	МАКСИМУМ(ОтветыНаВопросыАнкет.Ответ) КАК МАКСИМУМ,
	|	СРЕДНЕЕ(ВЫРАЗИТЬ(ОтветыНаВопросыАнкет.Ответ КАК ЧИСЛО)) КАК Среднее,
	|	СУММА(ВЫРАЗИТЬ(ОтветыНаВопросыАнкет.Ответ КАК ЧИСЛО)) КАК СУММА,
	|	КОЛИЧЕСТВО(ОтветыНаВопросыАнкет.Ответ) КАК КоличествоРазличных
	|ПОМЕСТИТЬ ДанныеРегистра
	|ИЗ
	|	РегистрСведений.ОтветыНаВопросыАнкет КАК ОтветыНаВопросыАнкет
	|ГДЕ
	|	ОтветыНаВопросыАнкет.Анкета.Опрос = &Опрос
	|	И ТИПЗНАЧЕНИЯ(ОтветыНаВопросыАнкет.Ответ) = ТИП(ЧИСЛО)
	|	И ОтветыНаВопросыАнкет.БезОтвета = ЛОЖЬ
	|СГРУППИРОВАТЬ ПО
	|	ОтветыНаВопросыАнкет.Вопрос,
	|	ОтветыНаВопросыАнкет.ЭлементарныйВопрос,
	|	ОтветыНаВопросыАнкет.НомерЯчейки
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	ОтветыНаВопросыАнкет.Вопрос,
	|	ОтветыНаВопросыАнкет.ЭлементарныйВопрос,
	|	ОтветыНаВопросыАнкет.НомерЯчейки,
	|	NULL,
	|	МИНИМУМ(ОтветыНаВопросыАнкет.Ответ),
	|	МАКСИМУМ(ОтветыНаВопросыАнкет.Ответ),
	|	СРЕДНЕЕ(0),
	|	СУММА(0),
	|	КОЛИЧЕСТВО(ОтветыНаВопросыАнкет.Ответ)
	|ИЗ
	|	РегистрСведений.ОтветыНаВопросыАнкет КАК ОтветыНаВопросыАнкет
	|ГДЕ
	|	ОтветыНаВопросыАнкет.Анкета.Опрос = &Опрос
	|	И ТИПЗНАЧЕНИЯ(ОтветыНаВопросыАнкет.Ответ) = ТИП(ДАТА)
	|	И ОтветыНаВопросыАнкет.БезОтвета = ЛОЖЬ
	|
	|СГРУППИРОВАТЬ ПО
	|	ОтветыНаВопросыАнкет.Вопрос,
	|	ОтветыНаВопросыАнкет.ЭлементарныйВопрос,
	|	ОтветыНаВопросыАнкет.НомерЯчейки
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	ОтветыНаВопросыАнкет.Вопрос,
	|	ОтветыНаВопросыАнкет.ЭлементарныйВопрос,
	|	ОтветыНаВопросыАнкет.НомерЯчейки,
	|	ОтветыНаВопросыАнкет.Ответ,
	|	NULL,
	|	NULL,
	|	NULL,
	|	NULL,
	|	КОЛИЧЕСТВО(ОтветыНаВопросыАнкет.Ответ)
	|ИЗ
	|	РегистрСведений.ОтветыНаВопросыАнкет КАК ОтветыНаВопросыАнкет
	|ГДЕ
	|	ОтветыНаВопросыАнкет.Анкета.Опрос = &Опрос
	|	И ТИПЗНАЧЕНИЯ(ОтветыНаВопросыАнкет.Ответ) = ТИП(БУЛЕВО)
	|	
	|СГРУППИРОВАТЬ ПО
	|	ОтветыНаВопросыАнкет.Вопрос,
	|	ОтветыНаВопросыАнкет.ЭлементарныйВопрос,
	|	ОтветыНаВопросыАнкет.НомерЯчейки,
	|	ОтветыНаВопросыАнкет.Ответ
	|			
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	ОтветыНаВопросыАнкет.Вопрос,
	|	ОтветыНаВопросыАнкет.ЭлементарныйВопрос,
	|	ОтветыНаВопросыАнкет.НомерЯчейки,
	|	NULL,
	|	NULL,
	|	NULL,
	|	NULL,
	|	NULL,
	|	КОЛИЧЕСТВО(ОтветыНаВопросыАнкет.Ответ)
	|ИЗ
	|	РегистрСведений.ОтветыНаВопросыАнкет КАК ОтветыНаВопросыАнкет
	|ГДЕ
	|	ОтветыНаВопросыАнкет.Анкета.Опрос = &Опрос
	|	И ТИПЗНАЧЕНИЯ(ОтветыНаВопросыАнкет.Ответ) <> ТИП(БУЛЕВО)
	|	И ТИПЗНАЧЕНИЯ(ОтветыНаВопросыАнкет.Ответ) <> ТИП(ДАТА)
	|	И ТИПЗНАЧЕНИЯ(ОтветыНаВопросыАнкет.Ответ) <> ТИП(ЧИСЛО)
	|	И ТИПЗНАЧЕНИЯ(ОтветыНаВопросыАнкет.Ответ) <> ТИП(Справочник.ВариантыОтветовАнкет)
	|	И ОтветыНаВопросыАнкет.БезОтвета = ЛОЖЬ
	|	
	|СГРУППИРОВАТЬ ПО
	|	ОтветыНаВопросыАнкет.Вопрос,
	|	ОтветыНаВопросыАнкет.ЭлементарныйВопрос,
	|	ОтветыНаВопросыАнкет.НомерЯчейки
	|;
	|////////////////////////////////////////////////////////////////////
	|
	|ВЫБРАТЬ
	|	ВопросыШаблонаАнкеты.Представление КАК Формулировка,
	|	ВопросыШаблонаАнкеты.ЭтоГруппа КАК ЭтоРаздел,
	|	ЕСТЬNULL(ВопросыДляАнкетирования.ТипОтвета, ЗНАЧЕНИЕ(Перечисление.ТипыОтветовНаВопрос.ПустаяСсылка)) КАК ТипОтвета,
	|	ВопросыШаблонаАнкеты.Ссылка КАК Ссылка,
	|	ЕСТЬNULL(ВопросыДляАнкетирования.АгрегироватьСуммуВОтчетах, ЛОЖЬ) КАК АгрегироватьСуммуВОтчетах
	|ПОМЕСТИТЬ ВопросыШаблонаАнкеты
	|ИЗ
	|	Справочник.ВопросыШаблонаАнкеты КАК ВопросыШаблонаАнкеты
	|	ЛЕВОЕ СОЕДИНЕНИЕ ПланВидовХарактеристик.ВопросыДляАнкетирования КАК ВопросыДляАнкетирования
	|		ПО ВопросыШаблонаАнкеты.ЭлементарныйВопрос = ВопросыДляАнкетирования.Ссылка
	|ГДЕ
	|	ВопросыШаблонаАнкеты.Владелец = &ШаблонАнкеты
	|	И (НЕ ВопросыШаблонаАнкеты.ЭтоГруппа)
	|;
	|////////////////////////////////////////////////////////////////////
	|
	|ВЫБРАТЬ
	|	ВопросыШаблонаАнкеты.ЭтоРаздел КАК ЭтоРаздел,
	|	ВопросыШаблонаАнкеты.ТипОтвета КАК ТипОтвета,
	|	ВопросыШаблонаАнкеты.Ссылка КАК Ссылка,
	|	ВопросыШаблонаАнкеты.АгрегироватьСуммуВОтчетах КАК АгрегироватьСуммуВОтчетах
	|ПОМЕСТИТЬ ВопросыШаблонаАнкетыВарианты
	|ИЗ 
	|	ВопросыШаблонаАнкеты КАК ВопросыШаблонаАнкеты
	|ГДЕ
	|	ВопросыШаблонаАнкеты.ТипОтвета <> ЗНАЧЕНИЕ(Перечисление.ТипыОтветовНаВопрос.ОдинВариантИз)
	|И ВопросыШаблонаАнкеты.ТипОтвета <> ЗНАЧЕНИЕ(Перечисление.ТипыОтветовНаВопрос.НесколькоВариантовИз)
	|;
	|////////////////////////////////////////////////////////////////////
	|
	|ВЫБРАТЬ
	|	ВопросыШаблонаАнкеты.Представление КАК Формулировка,
	|	ВопросыШаблонаАнкеты.ЭтоГруппа КАК ЭтоРаздел,
	|	ЕСТЬNULL(ВопросыДляАнкетирования.ТипОтвета, ЗНАЧЕНИЕ(Перечисление.ТипыОтветовНаВопрос.ПустаяСсылка)) КАК ТипОтвета,
	|	ВопросыШаблонаАнкеты.Ссылка КАК Ссылка,
	|	ВариантыОтветовАнкет.Ссылка КАК ВариантОтвета,
	|	ЕСТЬNULL(ВопросыДляАнкетирования.АгрегироватьСуммуВОтчетах, ЛОЖЬ) КАК АгрегироватьСуммуВОтчетах,
	|	ВариантыОтветовАнкет.РеквизитДопУпорядочивания КАК Код,
	|	ВопросыШаблонаАнкеты.ЭлементарныйВопрос КАК ЭлементарныйВопрос
	|ПОМЕСТИТЬ ВопросыШаблонаАнкетыВопросы
	|ИЗ
	|	Справочник.ВопросыШаблонаАнкеты КАК ВопросыШаблонаАнкеты
	|	ЛЕВОЕ СОЕДИНЕНИЕ ПланВидовХарактеристик.ВопросыДляАнкетирования КАК ВопросыДляАнкетирования
	|	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВариантыОтветовАнкет КАК ВариантыОтветовАнкет
	|		ПО ВопросыДляАнкетирования.Ссылка = ВариантыОтветовАнкет.Владелец
	|		ПО ВопросыШаблонаАнкеты.ЭлементарныйВопрос = ВопросыДляАнкетирования.Ссылка
	|ГДЕ
	|	ВопросыШаблонаАнкеты.Владелец = &ШаблонАнкеты
	|	И (НЕ ВопросыШаблонаАнкеты.ЭтоГруппа)
	|	И ВопросыДляАнкетирования.ТипОтвета В (ЗНАЧЕНИЕ(Перечисление.ТипыОтветовНаВопрос.ОдинВариантИЗ), ЗНАЧЕНИЕ(Перечисление.ТипыОтветовНаВопрос.НесколькоВариантовИз))
	|;
	|////////////////////////////////////////////////////////////////////
	|
	|ВЫБРАТЬ
	|	ОтветыНаВопросыАнкет.Вопрос КАК Вопрос,
	|	ОтветыНаВопросыАнкет.ЭлементарныйВопрос КАК ЭлементарныйВопрос,
	|	ОтветыНаВопросыАнкет.НомерЯчейки КАК НомерЯчейки,
	|	ОтветыНаВопросыАнкет.Ответ КАК Ответ
	|ПОМЕСТИТЬ ОтветыНаТабличныеВопросы
	|ИЗ
	|	РегистрСведений.ОтветыНаВопросыАнкет КАК ОтветыНаВопросыАнкет
	|	ЛЕВОЕ СОЕДИНЕНИЕ ПланВидовХарактеристик.ВопросыДляАнкетирования КАК ВопросыДляАнкетирования
	|		ПО ОтветыНаВопросыАнкет.ЭлементарныйВопрос = ВопросыДляАнкетирования.Ссылка
	|	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВопросыШаблонаАнкеты КАК ВопросыШаблонаАнкеты
	|		ПО ОтветыНаВопросыАнкет.Вопрос = ВопросыШаблонаАнкеты.Ссылка
	|ГДЕ
	|	ОтветыНаВопросыАнкет.Анкета.Опрос = &Опрос
	|	И (НЕ ВопросыШаблонаАнкеты.ТипТабличногоВопроса = ЗНАЧЕНИЕ(Перечисление.ТипыТабличныхВопросов.Составной))
	|	И ВопросыШаблонаАнкеты.ТипВопроса = ЗНАЧЕНИЕ(Перечисление.ТипыВопросовШаблонаАнкеты.Табличный)
	|	И ВопросыДляАнкетирования.ТипОтвета В (ЗНАЧЕНИЕ(Перечисление.ТипыОтветовНаВопрос.Булево), ЗНАЧЕНИЕ(Перечисление.ТипыОтветовНаВопрос.ОдинВариантИз), ЗНАЧЕНИЕ(Перечисление.ТипыОтветовНаВопрос.НесколькоВариантовИз))
	|;
	|////////////////////////////////////////////////////////////////////
	|
	|ВЫБРАТЬ
	|	ВопросыШаблонаАнкеты.Формулировка КАК Наименование,
	|	ВопросыШаблонаАнкеты.Ссылка КАК ВопросШаблона,
	|	ВопросыШаблонаАнкеты.ЭтоГруппа КАК ЭтоРаздел,
	|	ОсновнойЗапрос.ЭлементарныйВопросРегистр,
	|	ОсновнойЗапрос.НомерЯчейки КАК НомерЯчейки,
	|	ОсновнойЗапрос.ВариантОтвета,
	|	ЕСТЬNULL(ОсновнойЗапрос.КоличествоРазличных, 0) КАК Количество,
	|	ЕСТЬNULL(ОсновнойЗапрос.МИНИМУМ, 0) КАК МИНИМУМ,
	|	ЕСТЬNULL(ОсновнойЗапрос.МАКСИМУМ, 0) КАК МАКСИМУМ,
	|	ЕСТЬNULL(ОсновнойЗапрос.Среднее, 0) КАК Среднее,
	|	ЕСТЬNULL(ОсновнойЗапрос.СУММА, 0) КАК СУММА,
	|	ОсновнойЗапрос.ТипОтвета,
	|	ВопросыШаблонаАнкеты.ТипВопроса,
	|	ВопросыШаблонаАнкеты.ТипТабличногоВопроса,
	|	ВопросыШаблонаАнкеты.СоставТабличногоВопроса.(
	|		НомерСтроки,
	|		ЭлементарныйВопрос
	|	),
	|	ВопросыШаблонаАнкеты.ПредопределенныеОтветы.(
	|		НомерСтроки КАК НомерСтроки,
	|		ЭлементарныйВопрос КАК ЭлементарныйВопросОтвет,
	|		Ответ
	|	),
	|	ОсновнойЗапрос.АгрегироватьСуммуВОтчетах
	|{ВЫБРАТЬ
	|	ЭлементарныйВопрос.*}
	|ИЗ
	|	(ВЫБРАТЬ
	|		ВопросыШаблонаАнкетыВарианты.Ссылка                    КАК ВопросШаблона,
	|		ВопросыШаблонаАнкетыВарианты.ЭтоРаздел                 КАК ЭтоРаздел,
	|		ДанныеРегистра.ЭлементарныйВопрос                      КАК ЭлементарныйВопросРегистр,
	|		ДанныеРегистра.НомерЯчейки                             КАК НомерЯчейки,
	|		ДанныеРегистра.ВариантОтвета                           КАК ВариантОтвета,
	|		ДанныеРегистра.КоличествоРазличных                     КАК КоличествоРазличных,
	|		ДанныеРегистра.МИНИМУМ                                 КАК МИНИМУМ,
	|		ДанныеРегистра.МАКСИМУМ                                КАК МАКСИМУМ,
	|		ДанныеРегистра.Среднее                                 КАК Среднее,
	|		ДанныеРегистра.СУММА                                   КАК СУММА,
	|		ВопросыШаблонаАнкетыВарианты.ТипОтвета                 КАК ТипОтвета,
	|		ВопросыШаблонаАнкетыВарианты.АгрегироватьСуммуВОтчетах КАК АгрегироватьСуммуВОтчетах,
	|		0 КАК                                                  КодВариантаОтвета
	|	ИЗ
	|		ВопросыШаблонаАнкетыВарианты КАК ВопросыШаблонаАнкетыВарианты
	|			ЛЕВОЕ СОЕДИНЕНИЕ ДанныеРегистра КАК ДанныеРегистра
	|			ПО ВопросыШаблонаАнкетыВарианты.Ссылка = ДанныеРегистра.Вопрос
	|	
	|	ОБЪЕДИНИТЬ ВСЕ
	|	
	|	ВЫБРАТЬ
	|		ВопросыШаблонаАнкетыВопросы.Ссылка,
	|		ВопросыШаблонаАнкетыВопросы.ЭтоРаздел,
	|		ЕСТЬNULL(ДанныеРегистраБулевоВариантыОтветов.ЭлементарныйВопрос, ВопросыШаблонаАнкетыВопросы.ЭлементарныйВопрос),
	|		ДанныеРегистраБулевоВариантыОтветов.НомерЯчейки,
	|		ВопросыШаблонаАнкетыВопросы.ВариантОтвета,
	|		ДанныеРегистраБулевоВариантыОтветов.КоличествоРазличных,
	|		NULL,
	|		NULL,
	|		NULL,
	|		NULL,
	|		ВопросыШаблонаАнкетыВопросы.ТипОтвета,
	|		ВопросыШаблонаАнкетыВопросы.АгрегироватьСуммуВОтчетах,
	|		ВопросыШаблонаАнкетыВопросы.Код
	|	ИЗ
	|		ВопросыШаблонаАнкетыВопросы КАК ВопросыШаблонаАнкетыВопросы
	|			ЛЕВОЕ СОЕДИНЕНИЕ ДанныеРегистраБулевоВариантыОтветов КАК ДанныеРегистраБулевоВариантыОтветов
	|			ПО ВопросыШаблонаАнкетыВопросы.Ссылка = ДанныеРегистраБулевоВариантыОтветов.Вопрос
	|				И ВопросыШаблонаАнкетыВопросы.ВариантОтвета = ДанныеРегистраБулевоВариантыОтветов.ВариантОтвета
	|	
	|	ОБЪЕДИНИТЬ ВСЕ
	|	
	|	ВЫБРАТЬ
	|		ВопросыШаблонаАнкетыСоставТабличногоВопроса.Ссылка,
	|		ВопросыШаблонаАнкеты.ЭтоГруппа,
	|		ВопросыШаблонаАнкетыСоставТабличногоВопроса.ЭлементарныйВопрос,
	|		ОтветыНаТабличныеВопросы.НомерЯчейки,
	|		NULL,
	|		КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ОтветыНаТабличныеВопросы.Ответ),
	|		NULL,
	|		NULL,
	|		NULL,
	|		NULL,
	|		NULL,
	|		NULL,
	|		NULL
	|	ИЗ
	|		Справочник.ВопросыШаблонаАнкеты.СоставТабличногоВопроса КАК ВопросыШаблонаАнкетыСоставТабличногоВопроса
	|			ЛЕВОЕ СОЕДИНЕНИЕ ПланВидовХарактеристик.ВопросыДляАнкетирования КАК ВопросыДляАнкетирования
	|			ПО ВопросыШаблонаАнкетыСоставТабличногоВопроса.ЭлементарныйВопрос = ВопросыДляАнкетирования.Ссылка
	|			ЛЕВОЕ СОЕДИНЕНИЕ ОтветыНаТабличныеВопросы КАК ОтветыНаТабличныеВопросы
	|			ПО ВопросыШаблонаАнкетыСоставТабличногоВопроса.Ссылка = ОтветыНаТабличныеВопросы.Вопрос
	|				И ВопросыШаблонаАнкетыСоставТабличногоВопроса.ЭлементарныйВопрос = ОтветыНаТабличныеВопросы.ЭлементарныйВопрос
	|			ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВопросыШаблонаАнкеты КАК ВопросыШаблонаАнкеты
	|			ПО ВопросыШаблонаАнкетыСоставТабличногоВопроса.Ссылка = ВопросыШаблонаАнкеты.Ссылка
	|	ГДЕ
	|		ВопросыШаблонаАнкетыСоставТабличногоВопроса.Ссылка В
	|				(ВЫБРАТЬ
	|					ВопросыШаблонаАнкеты.Ссылка
	|				ИЗ
	|					Справочник.ВопросыШаблонаАнкеты КАК ВопросыШаблонаАнкеты
	|				ГДЕ
	|					ВопросыШаблонаАнкеты.ТипВопроса = ЗНАЧЕНИЕ(Перечисление.ТипыВопросовШаблонаАнкеты.Табличный)
	|					И ВопросыШаблонаАнкеты.Владелец = &ШаблонАнкеты
	|					И (НЕ ВопросыШаблонаАнкеты.ТипТабличногоВопроса = ЗНАЧЕНИЕ(Перечисление.ТипыТабличныхВопросов.Составной)))
	|		И ВопросыДляАнкетирования.ТипОтвета В (ЗНАЧЕНИЕ(Перечисление.ТипыОтветовНаВопрос.Булево), ЗНАЧЕНИЕ(Перечисление.ТипыОтветовНаВопрос.ОдинВариантИз), ЗНАЧЕНИЕ(Перечисление.ТипыОтветовНаВопрос.НесколькоВариантовИз))
	|	
	|	СГРУППИРОВАТЬ ПО
	|		ВопросыШаблонаАнкетыСоставТабличногоВопроса.Ссылка,
	|		ВопросыШаблонаАнкеты.ЭтоГруппа,
	|		ВопросыШаблонаАнкетыСоставТабличногоВопроса.ЭлементарныйВопрос,
	|		ОтветыНаТабличныеВопросы.НомерЯчейки) КАК ОсновнойЗапрос
	|		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВопросыШаблонаАнкеты КАК ВопросыШаблонаАнкеты
	|		ПО ОсновнойЗапрос.ВопросШаблона = ВопросыШаблонаАнкеты.Ссылка
	|
	|УПОРЯДОЧИТЬ ПО
	|	ВопросШаблона,
	|	ОсновнойЗапрос.КодВариантаОтвета,
	|	НомерЯчейки
	|ИТОГИ ПО
	|	ВопросШаблона ИЕРАРХИЯ";
	
	Запрос.УстановитьПараметр("Опрос", Опрос);
	Запрос.УстановитьПараметр("ШаблонАнкеты",ШаблонАнкеты);
	
	Возврат Запрос.Выполнить();
	
КонецФункции

// Параметры:
//   СтрокаДерева - СтрокаДереваЗначений
//
// Возвращаемое значение:
//   Строка
//
Функция АгрегатныеЗначенияВСтроку(СтрокаДерева,АгрегироватьСуммуВОтчетах = Неопределено)
	
	Если ТипЗнч(СтрокаДерева.Максимум) = Тип("Дата") Тогда
		Максимум = Формат(СтрокаДерева.Максимум, "ДЛФ=D");
	Иначе
		Максимум = Формат(ОКР(СтрокаДерева.Максимум,2),"ЧРД=.");
	КонецЕсли;
	
	Если ТипЗнч(СтрокаДерева.Минимум) = Тип("Дата") Тогда
		Минимум = Формат(СтрокаДерева.Минимум, "ДЛФ=D");
	Иначе
		Минимум = Формат(ОКР(СтрокаДерева.Минимум,2),"ЧРД=.");
	КонецЕсли;
	
	Количество = Формат(СтрокаДерева.Количество,"ЧРД=.");
	Среднее    = Формат(ОКР(СтрокаДерева.Среднее,2),"ЧРД=.");
	Сумма      = Формат(ОКР(СтрокаДерева.Сумма,2),"ЧРД=.");
	
	СтрокаСлэш = " / ";
	
	СтрокаВозврата = "" + ?(ПустаяСтрока(Количество),"",Количество) + Символы.ПС 
	+ ?(ПустаяСтрока(Минимум),"",Минимум + СтрокаСлэш)+ ?(ПустаяСтрока(Максимум),"",Максимум + СтрокаСлэш) + ?(ПустаяСтрока(Среднее),"",Среднее)
	+ ?(?(АгрегироватьСуммуВОтчетах = Неопределено,СтрокаДерева.АгрегироватьСуммуВОтчетах,АгрегироватьСуммуВОтчетах),Символы.ПС + ?(ПустаяСтрока(Сумма) = "∑ 0","","∑ " + Сумма),"");
	
	АнкетированиеКлиентСервер.УдалитьПоследниеСимволыИзСтроки(СтрокаВозврата,СтрокаСлэш);
	
	Возврат СтрокаВозврата;
	
КонецФункции

#КонецОбласти

#Область АнализОтветивших

// Параметры:
//  ТаблицаОтчета - ТабличныйДокумент - табличный документ, в который выводится отчет.
//  Опрос         - ДокументСсылка.НазначениеОпросов - опрос, для которого строится отчет.
//
Процедура СформироватьОтчетАнализОтветивших(ТаблицаОтчета,Опрос)

	РеквизитыОпрос = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Опрос,"ШаблонАнкеты,ТипРеспондентов,СвободныйОпрос,ДатаНачала,ДатаОкончания,Представление");
	
	Если РеквизитыОпрос.СвободныйОпрос Тогда
		РезультатЗапроса = ВыполнитьЗапросПоОтветившимСвободныйОпрос(Опрос, РеквизитыОпрос.ТипРеспондентов);
	Иначе
		РезультатЗапроса = ВыполнитьЗапросПоОтветившимОпросСОпределеннымСоставомРеспондентов(Опрос);
	КонецЕсли;
	Если РезультатЗапроса.Пустой() Тогда
		Возврат;
	КонецЕсли;
	
	ВывестиРезультатЗапросаОтветившиеВТабличныйДокумент(РезультатЗапроса,РеквизитыОпрос,ТаблицаОтчета);

КонецПроцедуры

// Параметры:
//  РезультатЗапроса - РезультатЗапроса  - результат выполненного запроса.
//  РеквизитыОпрос   - Структура - содержит значения необходимых реквизитов НазначениеОпроса.
//  ТаблицаОтчета   - ТабличныйДокумент - табличный документ в который выводится отчет.
//
Процедура ВывестиРезультатЗапросаОтветившиеВТабличныйДокумент(РезультатЗапроса,РеквизитыОпрос,ТаблицаОтчета)
	
	Макет = ПолучитьМакет("МакетОтветившие");
	
	Область = Макет.ПолучитьОбласть("Заголовок");// ТабличныйДокумент
	Область.Параметры.Заголовок = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(РеквизитыОпрос.ШаблонАнкеты, "Заголовок");
	Область.Параметры.Опрос 	= ПредставлениеОпросаДляЗаголовка(РеквизитыОпрос);
	ТаблицаОтчета.Вывести(Область,1);
	
	ВыборкаОбщиеИтоги = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
	Пока ВыборкаОбщиеИтоги.Следующий() Цикл
		
		ВывестиСтрокуОтветившиеВТабличныйДокумент(ВыборкаОбщиеИтоги,Макет,ТаблицаОтчета,"ОбщийИтог");
		ТаблицаОтчета.НачатьГруппуСтрок("ОбщийИтог");
		
		ВыборкаОтветил = ВыборкаОбщиеИтоги.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
		Пока ВыборкаОтветил.Следующий() Цикл
			ВывестиСтрокуОтветившиеВТабличныйДокумент(ВыборкаОтветил,Макет,ТаблицаОтчета,"ИтогОтветил");
			ТаблицаОтчета.НачатьГруппуСтрок("ОтветилИтог");
			ВыборкаДетали = ВыборкаОтветил.Выбрать();
			Пока ВыборкаДетали.Следующий() Цикл
				ВывестиСтрокуОтветившиеВТабличныйДокумент(ВыборкаДетали,Макет,ТаблицаОтчета,"Респондент");
			КонецЦикла;
			ТаблицаОтчета.ЗакончитьГруппуСтрок();
		КонецЦикла;
		ТаблицаОтчета.ЗакончитьГруппуСтрок();
	КонецЦикла;
	
КонецПроцедуры

// Параметры:
//  Выборка       - ВыборкаИзРезультатаЗапроса - выборка, в которой содержатся данные выводимые в отчет.
//  Макет         - ТабличныйДокумент - табличный документ, в котором находится макет отчета.
//  ТаблицаОтчета - ТабличныйДокумент - табличный документ, в который осуществляется вывод.
//  ИмяОбласти    - Строка - имя области макета,которая будет использована для вывода.
//
Процедура ВывестиСтрокуОтветившиеВТабличныйДокумент(Выборка,Макет,ТаблицаОтчета,ИмяОбласти);
	
	Область = Макет.ПолучитьОбласть(ИмяОбласти);
	Если Выборка.ТипЗаписи() = ТипЗаписиЗапроса.ОбщийИтог Тогда
		Область.Параметры.Количество = Выборка.Респондент;
	ИначеЕсли Выборка.ТипЗаписи() = ТипЗаписиЗапроса.ИтогПоГруппировке Тогда
		Область.Параметры.Количество = Выборка.Респондент;
		Область.Параметры.Ответил    = Выборка.Отвечал;
	Иначе
		Область.Параметры.Респондент = Выборка.Респондент;
	КонецЕсли;
	ТаблицаОтчета.Вывести(Область);
	
КонецПроцедуры

// Параметры:
//  Опрос - ДокументСсылка.НазначениеОпросов - опрос, для которого строится отчет.
//  
// Возвращаемое значение:
//   РезультатЗапроса
//
Функция ВыполнитьЗапросПоОтветившимОпросСОпределеннымСоставомРеспондентов(Опрос)
	
	Запрос = Новый Запрос;
	Запрос.Текст = "
	|ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	Анкета.Респондент,
	|	Анкета.Проведен
	|ПОМЕСТИТЬ ОтветившиеРеспонденты
	|ИЗ
	|	Документ.Анкета КАК Анкета
	|ГДЕ
	|	Анкета.Опрос = &Опрос
	|	И (НЕ Анкета.ПометкаУдаления)
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ВЫБОР
	|		КОГДА ОтветившиеРеспонденты.Респондент ЕСТЬ NULL 
	|			ТОГДА &НеЗаполнял
	|		ИНАЧЕ ВЫБОР
	|				КОГДА ОтветившиеРеспонденты.Проведен
	|					ТОГДА &Заполнил
	|				ИНАЧЕ &НачалЗаполнять
	|			КОНЕЦ
	|	КОНЕЦ КАК Отвечал,
	|	НазначениеОпросовРеспонденты.Респондент КАК Респондент
	|ИЗ
	|	Документ.НазначениеОпросов.Респонденты КАК НазначениеОпросовРеспонденты
	|		ЛЕВОЕ СОЕДИНЕНИЕ ОтветившиеРеспонденты КАК ОтветившиеРеспонденты
	|		ПО (ОтветившиеРеспонденты.Респондент = НазначениеОпросовРеспонденты.Респондент)
	|ГДЕ
	|	НазначениеОпросовРеспонденты.Ссылка = &Опрос
	|
	|УПОРЯДОЧИТЬ ПО
	|	Отвечал,
	|	Респондент
	|ИТОГИ
	|	КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Респондент)
	|ПО
	|	ОБЩИЕ,
	|	Отвечал";
	
	Запрос.УстановитьПараметр("Опрос",Опрос);
	Запрос.УстановитьПараметр("Заполнил",НСтр("ru = 'Заполнил'"));
	Запрос.УстановитьПараметр("НачалЗаполнять",НСтр("ru = 'Начал заполнять'"));
	Запрос.УстановитьПараметр("НеЗаполнял",НСтр("ru = 'Не заполнял'"));
	
	Возврат Запрос.Выполнить();
	
КонецФункции

// Параметры:
//  Опрос           - ДокументСсылка.НазначениеОпросов - опрос, для которого строится отчет.
//  ТипРеспондентов - СправочникСсылка - пустая ссылка на справочник, элементы которого являются 
//                    респондентами для данного опроса.
// Возвращаемое значение:
//   РезультатЗапроса
//
Функция ВыполнитьЗапросПоОтветившимСвободныйОпрос(Опрос,ТипРеспондентов)
	
	МетаданныеТипаРеспондентов = ТипРеспондентов.Метаданные();
	
	Запрос = Новый Запрос;
	Запрос.Текст = "
	|ВЫБРАТЬ
	|	ТаблицаСправочника.Ссылка
	|ПОМЕСТИТЬ ДанныеСправочника
	|ИЗ
	|	&ТаблицаСправочника КАК ТаблицаСправочника
	|ГДЕ
	|	(НЕ ТаблицаСправочника.ПометкаУдаления)
	|	И &ЭтоГруппа
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	Анкета.Респондент,
	|	Анкета.Проведен
	|ПОМЕСТИТЬ ОтветившиеРеспонденты
	|ИЗ
	|	Документ.Анкета КАК Анкета
	|ГДЕ
	|	(НЕ Анкета.ПометкаУдаления)
	|	И Анкета.Опрос = &Опрос
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ВЫБОР
	|		КОГДА ОтветившиеРеспонденты.Респондент ЕСТЬ NULL 
	|			ТОГДА &НеЗаполнял
	|		ИНАЧЕ ВЫБОР
	|				КОГДА ОтветившиеРеспонденты.Проведен
	|					ТОГДА &Заполнил
	|				ИНАЧЕ &НачалЗаполнять
	|			КОНЕЦ
	|	КОНЕЦ КАК Отвечал,
	|	ДанныеСправочника.Ссылка КАК Респондент
	|ИЗ
	|	ДанныеСправочника КАК ДанныеСправочника
	|		ЛЕВОЕ СОЕДИНЕНИЕ ОтветившиеРеспонденты КАК ОтветившиеРеспонденты
	|		ПО ДанныеСправочника.Ссылка = ОтветившиеРеспонденты.Респондент
	|
	|УПОРЯДОЧИТЬ ПО
	|	Отвечал,
	|   Респондент
	|ИТОГИ
	|	КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Респондент)
	|ПО
	|	ОБЩИЕ,
	|	Отвечал";
	
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ТаблицаСправочника", МетаданныеТипаРеспондентов.ПолноеИмя());
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ЭтоГруппа", 
		?(МетаданныеТипаРеспондентов.Иерархический И МетаданныеТипаРеспондентов.ВидИерархии = Метаданные.СвойстваОбъектов.ВидИерархии.ИерархияГруппИЭлементов,
	         "НЕ ТаблицаСправочника.ЭтоГруппа", "ИСТИНА"));
	
	Запрос.УстановитьПараметр("Опрос",Опрос);
	Запрос.УстановитьПараметр("Заполнил",НСтр("ru = 'Заполнил'"));
	Запрос.УстановитьПараметр("НачалЗаполнять",НСтр("ru = 'Начал заполнять'"));
	Запрос.УстановитьПараметр("НеЗаполнял",НСтр("ru = 'Не заполнял'"));
	
	Возврат Запрос.Выполнить();
	
КонецФункции

#КонецОбласти

#Область Прочее

Функция ПредставлениеОпросаДляЗаголовка(РеквизитыОпроса)
	
	Если РеквизитыОпроса.ДатаНачала <> Дата(1, 1, 1) И РеквизитыОпроса.ДатаОкончания <> Дата(1, 1, 1) Тогда
		Результат = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Опрос проводился в период с %1 по %2 на основании документа %3.'"),
			Формат(РеквизитыОпроса.ДатаНачала, "ДЛФ=ДД"), Формат(РеквизитыОпроса.ДатаОкончания, "ДЛФ=ДД"),
			РеквизитыОпроса.Представление);
	ИначеЕсли РеквизитыОпроса.ДатаНачала <> Дата(1, 1, 1) Тогда
		Результат = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Опрос проводился в период с %1 на основании документа %2.'"),
			Формат(РеквизитыОпроса.ДатаНачала, "ДЛФ=ДД"), 
			РеквизитыОпроса.Представление);
	ИначеЕсли РеквизитыОпроса.ДатаОкончания <> Дата(1, 1, 1) Тогда
		Результат = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Опрос проводился в период по %1 на основании документа %2.'"),
			Формат(РеквизитыОпроса.ДатаОкончания, "ДЛФ=ДД"), 
			РеквизитыОпроса.Представление);
	Иначе
		Результат = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Опрос на основании документа %1.'"),
			РеквизитыОпроса.Представление);
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции

#КонецОбласти

#КонецОбласти

#Иначе
ВызватьИсключение НСтр("ru = 'Недопустимый вызов объекта на клиенте.'");
#КонецЕсли